/*
 *  Copyright 2005 Blandware (http://www.blandware.com)
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.blandware.atleap.persistence.hibernate.questionnaire;

import com.blandware.atleap.persistence.hibernate.core.BaseDAOHibernate;
import com.blandware.atleap.persistence.questionnaire.FilledQuestionnaireDAO;
import com.blandware.atleap.model.questionnaire.FilledQuestionnaire;
import com.blandware.atleap.model.questionnaire.Questionnaire;
import com.blandware.atleap.model.questionnaire.Answer;
import com.blandware.atleap.model.questionnaire.AnswerOption;
import com.blandware.atleap.common.util.PartialCollection;
import com.blandware.atleap.common.util.QueryInfo;

import java.util.*;

/**
 * <p>Hibernate implementation of FilledQuestionnaireDAO.</p>
 * <p><a href="FilledQuestionnaireDAOHibernate.java.html"><i>View source</i></a></p>
 *
 * @author Roman Puchkovskiy <a href="mailto:roman.puchkovskiy@blandware.com">
 *         &lt;roman.puchkovskiy@blandware.com&gt;</a>
 * @version $Revision: 1.3 $ $Date: 2008/06/23 13:24:55 $
 */
public class FilledQuestionnaireDAOHibernate extends BaseDAOHibernate
        implements FilledQuestionnaireDAO {

    // ~ CRUD methods ================================================================

    /**
     * @see com.blandware.atleap.persistence.questionnaire.FilledQuestionnaireDAO#createFilledQuestionnaire(com.blandware.atleap.model.questionnaire.FilledQuestionnaire, com.blandware.atleap.model.questionnaire.Questionnaire)
     */
    public Long createFilledQuestionnaire(
            FilledQuestionnaire filledQuestionnaire,
            Questionnaire questionnaire) {
        filledQuestionnaire.setDate(new Date());
        questionnaire.addFilledQuestionnaire(filledQuestionnaire);
        return (Long) getHibernateTemplate().save(filledQuestionnaire);
    }

    /**
     * @see com.blandware.atleap.persistence.questionnaire.FilledQuestionnaireDAO#retrieveFilledQuestionnaire(Long)
     */
    public FilledQuestionnaire retrieveFilledQuestionnaire(Long filledQuestionnaireId) {
        return (FilledQuestionnaire) getHibernateTemplate().get(FilledQuestionnaire.class, filledQuestionnaireId);
    }

    /**
     * @see com.blandware.atleap.persistence.questionnaire.FilledQuestionnaireDAO#deleteFilledQuestionnaire(com.blandware.atleap.model.questionnaire.FilledQuestionnaire)
     */
    public void deleteFilledQuestionnaire(FilledQuestionnaire filledQuestionnaire) {
        // break relations between answers and options
        List answers = new ArrayList(filledQuestionnaire.getAnswers());
        for (Iterator i = answers.iterator(); i.hasNext(); ) {
            Answer answer = (Answer) i.next();
            List answerOptions = new ArrayList(answer.getAnswerOptions());
            for (Iterator j = answerOptions.iterator(); j.hasNext(); ) {
                AnswerOption answerOption = (AnswerOption) j.next();
                answer.removeAnswerOption(answerOption);
            }
        }

        getHibernateTemplate().delete(filledQuestionnaire);
        filledQuestionnaire.getQuestionnaire().removeFilledQuestionnaire(filledQuestionnaire);
    }

    // ~ Additional methods ================================================================

    /**
     * @see com.blandware.atleap.persistence.questionnaire.FilledQuestionnaireDAO#listFilledQuestionnaires(com.blandware.atleap.common.util.QueryInfo)
     */
    public PartialCollection listFilledQuestionnaires(QueryInfo queryInfo) {
		String whereClause = new String();
		String orderByClause = new String();
		if ( queryInfo != null ) {
			whereClause = queryInfo.getWhereClause();
			orderByClause = queryInfo.getOrderByClause();
		}

		if ( whereClause == null || whereClause.length() == 0 ) {
			whereClause = new String();
		}
		if ( orderByClause != null && orderByClause.length() != 0 ) {
			orderByClause = " order by " + orderByClause;
		} else {
			orderByClause = " order by fq.date desc ";
		}

		List list = null;
		Integer total = null;

		String localeIdentifier = null;
		if ( queryInfo != null ) {
			if ( queryInfo.getQueryParameters() != null ) {
				localeIdentifier = (String) queryInfo.getQueryParameters().get("localeIdentifier");
			}
		}

		boolean localeIdentifierPresent = localeIdentifier != null && localeIdentifier.length() > 0;

		String hqlPart = new String();
		ArrayList args = new ArrayList();
		if ( localeIdentifierPresent ) {
			args.add(localeIdentifier);
			hqlPart = new StringBuffer("from FilledQuestionnaire as fq ")
			        .append("left outer join fq.questionnaire.contentFields as titleField ")
			        .append("left outer join titleField.contentFieldValues as title ")
			        .append("where ")
			        .append("titleField.identifier = 'title' ")
			        .append("and title.contentLocale.identifier = ? ")
			        .toString();
			if ( whereClause.length() > 0 ) {
				hqlPart += "and " + whereClause;
			}
		} else {
            hqlPart = "from FilledQuestionnaire fq ";
            if ( whereClause.length() > 0 ) {
                hqlPart += "where " + whereClause;
            }
		}

		if ( queryInfo != null && queryInfo.getLimit() != null && queryInfo.getOffset() != null ) {
			// query count
			String hqlForTotal = "select count(distinct fq.id) " + hqlPart;
			total = findUniqueIntegerResult(hqlForTotal, args.toArray());
			if ( total == null ) {
				total = new Integer(0);
			}
		}

        // If we don't have any info about the total number of results yet or
        // we know that there's something that will be found, then fetch data
		if ( total == null || total.intValue() > 0 ) {
			String hql;
			if ( localeIdentifierPresent ) {
				hql = "select distinct fq, title.simpleValue " + hqlPart + orderByClause;
			} else {
				hql = "select distinct fq " + hqlPart + orderByClause;
			}
			list = executeFind(hql, queryInfo, args.toArray());
			if ( total == null ) {
				total = new Integer(list.size());
			}
			if ( localeIdentifierPresent ) {
				for ( ListIterator i = list.listIterator(); i.hasNext(); ) {
					Object[] objects = (Object[]) i.next();
					FilledQuestionnaire filledQuestionnaire = (FilledQuestionnaire) objects[0];
					filledQuestionnaire.getQuestionnaire().getTitle().put(localeIdentifier, objects[1]);
					i.set(filledQuestionnaire);
				}
			}
		} else {
			list = new ArrayList();
		}

		return new PartialCollection(list, total);
    }
}
